#include <stdio.h>
#include <string.h>
#include <stdint.h>

static inline void cpuid( int code, uint32_t * a , uint32_t * b, uint32_t * c, uint32_t * d ) {
    // issue cpuid opcode
    asm volatile( "cpuid" : "=a"(*a),
                            "=b"(*b),
                            "=c"(*c),
                            "=d"(*d) : "a"(code) );
}

void vendor_strcpy( char * v, uint32_t a, uint32_t b, uint32_t c ) {
    memcpy( v + 0, &a, 4 );
    memcpy( v + 4, &b, 4 );
    memcpy( v + 8, &c, 4 );
    v[12] = '\0';
}

bool inside_vm( void ) {
    uint32_t eax, ebx, ecx, edx;
    char vendor[13];
    bool virtualized = false;
    
    cpuid( 0x1, &eax, &ebx, &ecx, &edx );
    
    const uint32_t bit31 = ( 1 << 31 );
    
    if( bit31 & ecx ) {
        cpuid( 0x40000000, &eax, &ebx, &ecx, &edx );
        vendor_strcpy( vendor, ebx, ecx, edx );
        virtualized = true;
    }
    else {
        cpuid( 0x0, &eax, &ebx, &ecx, &edx );
        vendor_strcpy( vendor, ebx, edx, ecx );
        virtualized = false;
    }
    printf( "virtualized=%s\n", virtualized ? "true" : "false" );
    printf( "vendor=%s\n", vendor );
    return false;
}

int main( int argc, char ** argv ) {
    inside_vm();
    return 0;
}

